home *** CD-ROM | disk | FTP | other *** search
/ AOL File Library: 4,401 to 4,500 / aol-file-protocol-4400-4401-to-4500.zip / AOLDLs / PDA-Newton Development / ND+ Package Format!!!!!! / pfrmat.txt < prev   
Text File  |  2014-12-08  |  20KB  |  465 lines

  1.  
  2.  
  3. Well here it is!  Many thanks to David Fedor for his help on this.  I would guess that we each got 90% independently, combining our knowledge made it 95% and the resulting synergy bumped it up to 99%.  It's up to you to fill in the remaining 1%╔
  4.  
  5. This header file is being placed in the uiowa submissions directory as nwtpkg.h.
  6.  
  7. Cheers,
  8.  
  9.  
  10. Matthew ------8<----Cut Here----8<-----#ifndef NWT_PACKAGE_FORMAT_H #define NWT_PACKAGE_FORMAT_H /* Newton package file format header file.
  11.  *
  12.  * - This file is distributed in the hope that it will be useful, but
  13.  *    WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15.  *  - This file is freely distributable.
  16.  *  - The information in this file can be used in other products without
  17.  *    acknowledgement (though acknowledgement would be nice).
  18.  *  - If the information in this file is republished it's source should be
  19.  *    acknowledged.
  20.  *  - If the information is republished with changes, it's source should be
  21.  *    acknowledged and my responsibility for the changes disclaimed.
  22.  *
  23.  * This file contains information that was derived (with permission) from a
  24.  * file that is copyright 1994 by David Fedor.  His contribution to the
  25.  * discovery of the information in this file is gratefully acknowledged as
  26.  * is his generosity for allowing it to be passed on.  All errors and
  27.  * omissions are, of course, my own.
  28.  *
  29.  * Apple and Newton are trademarks of Apple Computer, Inc., registered in
  30.  * the United States and other countries.  MessagePad, NewtonScript and
  31.  * Newton ToolKit are trademarks of Apple Computer, Inc.
  32.  *
  33.  * Document history:
  34.  *
  35.  * v1.0     13 Dec 1994     Matthew Faupel
  36.  *  Initial version.
  37.  */
  38.  
  39. /* The format of a package file is as follows:
  40.  *
  41.  * FixedPkgHdr
  42.  * PartHdr[partCount]
  43.  * authorCopyright[]
  44.  * packageName[]
  45.  * partDescription[partCount][]
  46.  * NTKcopyright[]
  47.  * records[╔]
  48.  *
  49.  * Each of these is described below.
  50.  */
  51.  
  52. /* Types used in the header structure.  The lengths given following the
  53.  * types must be true for this file definition header to be correct.  If
  54.  * these typedefs do not result in types of the given lengths on your
  55.  * system, adjust them so that they do.
  56.  */ typedef unsigned char   uchar;      /* 1 byte */ typedef unsigned short  unichar;    /* 2 bytes (Unicode character) */ typedef unsigned short  ushort;     /* 2 bytes */ typedef unsigned long   ulong;      /* 4 bytes */
  57.  
  58. /* Characters in the package signature
  59.  */ #define PF_PACKAGE_SIG  "package0" #define PF_PACKAGE_SIG_LENGTH   (sizeof(PF_PACKAGE_SIG)-1)
  60.  
  61. /* Flags used in the package header:
  62.  *  Package will not be compressed on the newt
  63.  */ #define PF_UNCOMPRESSED  0x10000000
  64.  
  65. /*  Can't copy this package
  66.  */ #define PF_COPYPROTECTED 0x40000000
  67.  
  68. /*  Set on a dispatch-only auto part
  69.  */ #define PF_DISPATCHONLY  0x80000000
  70.  
  71. struct  _FixedPkgHdr {
  72.     /* Signature to indicate that this is a package file (the characters
  73.      * 'package0'; note that it is not NUL terminated).
  74.      */
  75.     char    packageSig[PF_PACKAGE_SIG_LENGTH]; /* PF_PACKAGE_SIG */
  76.  
  77.     /* Four more readable characters; usage unknown.  Characters that have
  78.      * been seen are: 'xxxx', ' no ' and 'none'.
  79.      */
  80.     char    something[4];
  81.  
  82.     /* Combination of the PF_ flags defined above.
  83.      */
  84.     ulong   packageFlags;
  85.  
  86.     /* Version number of the package as supplied by the developer.  Note
  87.      * that this is a whole integer.
  88.      */
  89.     ulong   versionNo;
  90.     ushort  zeroPad1;
  91.  
  92.     /* Length of the author+copyright string supplied in the subsequent
  93.      * strings section of the header.  Repeated for some reason.
  94.      */
  95.     ushort  authorCopyrightLength;
  96.     ushort  authorCopyrightLength2;
  97.  
  98.     /* Length of the package name string supplied in the subsequent strings
  99.      * section of the header.
  100.      */
  101.     ushort  packageNameLength;
  102.  
  103.     /* Length of the entire package file.
  104.      */
  105.     ulong   packageLength;
  106.  
  107.     /* File creation and modification timestamps (Apple format, i.e. seconds
  108.      * since 00:00 1 Jan 1904, local time).  The two values are normally
  109.      * identical, though the modified time has been 0 in some cases.
  110.      */
  111.     ulong   createdTimeStamp;
  112.     ulong   modifiedTimeStamp;
  113.     ulong   zeroPad2;
  114.  
  115.     /* Offset in the file of the first non-header record.
  116.      */
  117.     ulong   firstRecordOffset;
  118.  
  119.     /* Number of parts in this package.
  120.      */
  121.     ulong   partCount; }; typedef struct _FixedPkgHdr FixedPkgHdr;
  122.  
  123.  
  124. /* The fixed package header is followed immediately by an array of PartData
  125.  * items.  The number of items is given by the partCount field of the
  126.  * header.
  127.  */ struct  _PartHdr {
  128.     /* Offset of start of part data (from firstRecordOffset in header).
  129.      */
  130.     ulong   partOffset;
  131.  
  132.     /* Length of the data in the part (repeated for some reason)
  133.      */
  134.     ulong   lengthOfData;
  135.     ulong   lengthOfData2;
  136.  
  137.     /* 'form', 'book', 'auto' etc.  All values I have seen have only been
  138.      * four characters, so this field might only be 4 characters.  However,
  139.      * the following four characters are always zero and I've seen a
  140.      * technical paper which says that type 'auto!' is a valid type, hence I
  141.      * reckon the field is in fact 8 characters long.
  142.      */
  143.     uchar   partType[8];
  144.  
  145.     /* Unknown use.  Always 0x00000081.
  146.      */
  147.     ulong   value00000081;
  148.  
  149.     /* Offset (from beginning of strings block) and length of the string
  150.      * describing this part.  This is often just the part type repeated
  151.      * (e.g. "form"), but can be anything.
  152.      */
  153.     ushort  partStringOffset;
  154.     ushort  partStringLength;
  155.     ulong   zeroPad1; }; typedef struct _PartHdr PartHdr;
  156.  
  157. /* Following the part data is a block of variable length strings.  These
  158.  * are:
  159.  */
  160.  
  161. /* Copyright string from NTK project window.  NULNUL terminated.  Length
  162.  * given by authorCopyrightLength in the header.
  163.  *
  164.  * unichar authorCopyright[];
  165.  */
  166.  
  167. /* Name of package as seen in "Remove Software".  NULNUL terminated.  Length
  168.  * given by packageNameLength in the header.
  169.  *
  170.  * unichar packageName[];
  171.  */
  172.  
  173. /* Part description (as many of these as there are parts).  Not necessarily
  174.  * NUL terminated.  Length(s) given in the appropriate part header(s).
  175.  *
  176.  * char    partString[];
  177.  */
  178.  
  179. /* Copyright string inserted by NTK.  This is padded with trailing bytes
  180.  * containing 0xFF such that the next data (which is the first record of the
  181.  * package proper and is pointed to by firstRecordOffset) is on a four byte
  182.  * boundary relative to the start of the file.
  183.  *
  184.  * char    NTKcopyright[];
  185.  */
  186.  
  187.  
  188. /* Before going into the details of the three types of data, a quick
  189.  * introduction to vpums (a name coined by David Fedor).  "vpum" is the name
  190.  * given to the 32 bit values used by the Newton; it's an acronym derived
  191.  * from Value, Pointer, Unusual and Magic-pointer, that being the four types
  192.  * of data that the value can represent.
  193.  *
  194.  * The type information is encoded in the lowest two bits of the 32 bit
  195.  * value and the upper 30 bits contain the value information.  The types,
  196.  * what they represent and how they are interpreted are as follows:
  197.  *
  198.  * Low bits Type    Interpretation
  199.  * ------------------------------------------------------------------------* 00       Value   An immediate signed 30-bit integer value.  The integer
  200.  *                  is derived by doing a signed right shift by 2, e.g.
  201.  *                  0x00000100 = integer 64 (decimal),
  202.  *                  0xFFFFFFFC = integer -1 (decimal).
  203.  *
  204.  * 01       Pointer In memory, a pointer to another NewtonScript record, in
  205.  *                  the package file an absolute offset to another record.
  206.  *                  The exact address/offset is obtained by masking out the
  207.  *                  low two bits of the 32-bit value, e.g. 0x00000105 means
  208.  *                  offset 0x0104 in the package.
  209.  *
  210.  * 10       Unusual Used to encode a variety of immediate values.  The ones
  211.  *                  that I have come across are:
  212.  *                  0x00000002  - Nil
  213.  *                  0x0000001A  - True
  214.  *                  0x000UUUU6  - Unicode character \uUUUU, e.g. 0x00000416
  215.  *                  is the NewtonScript constant $A
  216.  *                  0x00055552  - Symbol class (explained below)
  217.  *
  218.  * 11       Magic   The value encodes a NewtonScript magic pointer, the
  219.  *                  values represented in NewtonScript as @nnnn and used to
  220.  *                  refer to built-in objects in NewtonOS.  The magic
  221.  *                  pointer number is derived from the 32-bit value by
  222.  *                  dividing by 4, e.g. 0x00000007 is @1.
  223.  */ typedef ulong   vpum;
  224.  
  225. #define VPUM_TYPE(v)        ((v)&0x03) #define VPUM_TYPE_VALUE     0 #define VPUM_TYPE_POINTER   1 #define VPUM_TYPE_UNUSUAL   2 #define VPUM_TYPE_MAGIC     3
  226.  
  227. #define VPUM_AS_VALUE(v)    (((long) (v)) >> 2) #define VPUM_AS_POINTER(v)  ((v) & 0xFFFFFFFC) #define VPUM_AS_UNICODE(v)  ((unichar) ((v) >> 4)) #define VPUM_AS_MAGIC(v)    ((v) >> 2)
  228.  
  229. #define VPUM_NIL            0x00000002 #define VPUM_TRUE           0x0000001A #define VPUM_SYMBOL_CLASS   0x00055552
  230.  
  231.  
  232. /* Back to the record╔ following the header data are the records for the
  233.  * package.  These are always aligned on an 8-byte boundary relative to
  234.  * firstRecordOffset, which itself is aligned on a 4-byte boundary relative
  235.  * to the start of the file.  The "gaps" between the records are filled with
  236.  * rubbish, quite often (but not always) this is 0xBABA╔ or 0xBADBADBA╔
  237.  *
  238.  * Data records have the following general format:
  239.  */
  240.  
  241. #define PF_RECORD_TYPE_DATA     0x40 #define PF_RECORD_TYPE_ARRAY    0x41 #define PF_RECORD_TYPE_FRAME    0x43
  242.  
  243. struct  _PkgRecord {
  244.     /* Note that only 3 bytes are used to hold the length of the record.
  245.      */
  246.     uchar   recordLength[3];
  247.  
  248.     /* This byte indicates what the record represents, one of raw data, a
  249.      * NewtonScript array or a NewtonScript frame.  The three values used
  250.      * are given above.
  251.      */
  252.     uchar   recordType;
  253.  
  254.     /* These flags are always zero in the package file, though I believe
  255.      * that the in-memory representation of this data is similar to the
  256.      * in-file representation and when in-memory this flags field is used.
  257.      */
  258.     ulong   recordFlags;
  259.  
  260.     /* This gives more detailed information about the record.  The exact
  261.      * meaning of the field depends on the recordType.  See below.
  262.      */
  263.     vpum    recordClass;
  264.  
  265.     /*      data follows here if record has data╔ see below.
  266.      */ }; typedef struct _PkgRecord  PkgRecord;
  267.  
  268. #define PF_RECORD_LENGTH(r) ((((ulong) (r).recordLength[0]) << 16) + \
  269.                              (((ulong) (r).recordLength[1]) << 8) + \
  270.                              (r).recordLength[2])
  271.  
  272.  
  273. /* Data records. (recordType = 0x40).
  274.  *
  275.  * Data records are used to represent any NewtonScript data that is not an
  276.  * array or frame.  Examples of this type of data are Unicode strings,
  277.  * icons, symbols and so on.
  278.  *
  279.  * For data records, the recordClass field contains a vpum that indicates
  280.  * the class of the data.  Usually this is an offset to another data record
  281.  * that gives the symbol naming the data type.  For instance, for unicode
  282.  * strings, the recordClass field will be an offset to a symbol record
  283.  * defining the symbol "String".  Immediately following the recordClass
  284.  * field comes the byte data for the record.  As an example, a String record
  285.  * might look like this:
  286.  *
  287.  * 00 00 16 40  Length = 22, type = data
  288.  * 00 00 00 00  Flags = 0 (as always)
  289.  * 00 00 02 85  Offset of String symbol record (see below)
  290.  * 00 46 00 72  Unicode string "Fred" including terminating NULNUL.
  291.  * 00 65 00 64
  292.  * 00 00
  293.  *
  294.  * Symbol records are a special type of data record.  Their recordClass is
  295.  * always the "unusual" type vpum 0x00055552 and the data is a four byte
  296.  * hash value, followed by the (ASCII not Unicode) string giving the symbol
  297.  * name.  The string is NUL terminated.  For instance, the following is the
  298.  * symbol record for the symbol "String":
  299.  *
  300.  * 00 00 17 40  Length = 23, type = data
  301.  * 00 00 00 00  Flags = 0
  302.  * 00 05 55 52  VPUM_SYMBOL_CLASS
  303.  * 18 10 F3 5F  Hash value
  304.  * 53 74 72 69  "String"
  305.  * 6E 67 00
  306.  *
  307.  * The hash value for symbols is calculated by the formula:
  308.  *
  309.  *  (Sum of toupper( c ) ) * 0x9e3779b9
  310.  *
  311.  * for all characters "c" in the symbol.
  312.  */ struct  _DataRecord {
  313.     uchar   recordLength[3];
  314.     uchar   recordType;         /* 0x40 */
  315.     ulong   recordFlags;        /* 0 */
  316.     vpum    recordClass;        /* Offset to symbol record */
  317.     uchar   recordData[1]; }; typedef struct _DataRecord  DataRecord; #define PF_DATA_SIZE(r)    (PF_RECORD_LENGTH(r)-sizeof(PkgRecord))
  318.  
  319. struct  _SymbolRecord {
  320.     uchar   recordLength[3];
  321.     uchar   recordType;         /* 0x40 */
  322.     ulong   recordFlags;        /* 0 */
  323.     vpum    recordClass;        /* VPUM_SYMBOL_CLASS */
  324.     ulong   symbolHashValue;
  325.     uchar   symbolName[1]; }; typedef struct _SymbolRecord    SymbolRecord; #define PF_SYMBOL_LENGTH(r) (PF_RECORD_LENGTH(r)-sizeof(SymbolRecord)+1)
  326.  
  327. /* Array records. (recordType = 0x41).
  328.  *
  329.  * Array records are used to represent NewtonScript arrays, both untyped
  330.  * ( [ x, y, z ] ) and typed ( [type: x, y, z ] ).  They are also used to
  331.  * represent certain internal arrays.
  332.  *
  333.  * Similar to data records, the recordClass field of an array record
  334.  * normally points to a symbol record indicating the type of the data.  So,
  335.  * for instance, for an array of stepChildren the recordClass field points
  336.  * to a symbol record defining the symbol "stepChildren".  For untyped
  337.  * NewtonScript arrays, the recordClass field points to a symbol record for
  338.  * the symbol "Array".
  339.  *
  340.  * The contents of the array are represented by a series of vpums following
  341.  * the recordClass.  Immediate values are represented by immediate value
  342.  * vpums; array elements that are themselves complex types are represented
  343.  * by vpum offsets to other records.
  344.  *
  345.  * Certain array records representing internal housekeeping arrays have
  346.  * recordClass values that are not offsets to symbol records.  The two that
  347.  * I have come across are the value VPUM_NIL, which is used for the very
  348.  * first record in any part data, and a vpum integer value used for frame
  349.  * maps, which are explained in more detail below.
  350.  *
  351.  * A quick digression into the format of the part data.  As far as I can
  352.  * tell, the first record read is always an array record with recordClass
  353.  * VPUM_NIL, as mentioned above.  This contains one element which is an
  354.  * offset to a frame record.  This frame record then contains all the
  355.  * information about the part, be it book, form or whatever.
  356.  *
  357.  * An example of the encoding of a NewtonScript array (courtesy of David
  358.  * Fedor):
  359.  *
  360.  * NewtonScript array:  [6, nil, @180]
  361.  * Equivalent record:
  362.  *
  363.  * 00 00 18 41  Length = 24, type = array
  364.  * 00 00 00 00  Flags = 0
  365.  * 00 00 07 09  vpum offset to symbol record for "Array"
  366.  * 00 00 00 18  vpum 0x18 is immediate value 6
  367.  * 00 00 00 02  vpum 0x2 is Nil
  368.  * 00 00 02 D3  vpum 0x2d3 is magic ptr @180
  369.  */ struct  _ArrayRecord {
  370.     uchar   recordLength[3];
  371.     uchar   recordType;         /* 0x41 */
  372.     ulong   recordFlags;        /* 0 */
  373.     vpum    recordClass;
  374.     vpum    arrayElement[1]; }; typedef struct _ArrayRecord ArrayRecord; #define PF_ARRAY_SIZE(r) ((PF_RECORD_LENGTH(r)-sizeof(PkgRecord))/sizeof(vpum))
  375.  
  376.  
  377. /* Frame records. (recordType = 0x43).
  378.  *
  379.  * Frame records are (surprise, surprise :-) used to represent NewtonScript
  380.  * frames.  For frame records, the recordClass field is always an offset to
  381.  * a frame map array (explained shortly).  The contents of the slots of the
  382.  * frame are then represented by a block of vpums following the recordClass
  383.  * (in a similar fashion to array elements for array records).  Which value
  384.  * belongs to which slot is determined by the frame map - the values are in
  385.  * the same order as the slot names in the map.
  386.  *
  387.  * Speaking of which:  The frame map is an array record containing vpum
  388.  * offsets to the symbol records that define the names of the slots in the
  389.  * frame, so the full representation of a frame is something like:
  390.  *
  391.  * FrameRecord          /--> ArrayRecord
  392.  *   recordLength;      |      recordLength;
  393.  *   recordType  = 0x43 |      recordType = 0x41
  394.  *   recordFlags = 0    |      recordFlags = 0
  395.  *   recordClass -------/      recordClass = see (1) below
  396.  *   <slot 0 value>            NIL (but see (2) below)
  397.  *   <slot 1 value>            ------------> SymbolRecord for name of slot 0
  398.  *   ╔                       ------------> SymbolRecord for name of slot 1
  399.  *                             ╔
  400.  *
  401.  * (1)  The recordClass of a frame map record is a combination of flags
  402.  *      giving information about the contents of the frame map.  The flags
  403.  *      are:
  404.  *          0x00000004  Frame map is sorted by symbol hash value
  405.  *                      Frames containing 21 or more slots are sorted by
  406.  *                      slot name hash value (for lookup speed), with the
  407.  *                      exception of CodeBlock _argFrame frames (which rely
  408.  *                      on ordering to match up with the NewtonScript
  409.  *                      bytecode).  This flag is set when this has been
  410.  *                      done.
  411.  *          0x00000008  I don't know - please tell me if you figure it out!
  412.  *                      It seems to have something to do with whether the
  413.  *                      frame is a normal frame or part of a proto or other
  414.  *                      frame not used directly, but that's not it
  415.  *                      exactly╔
  416.  *          0x00000010  Frame map contains a _proto slot.
  417.  *
  418.  * (2)  In the majority of cases, the first element of the frame map is NIL,
  419.  *      however occasionally it is a vpum offset to another frame map array.
  420.  *      If this is the case, then the elements of the pointed to array are
  421.  *      counted *before* those of the original map when working out which
  422.  *      symbol to use for a slot name.  e.g. if we have the following:
  423.  *
  424.  *      Frame         /-> Array            /-> Array
  425.  *       recordClass -/    recordClass = 0 |    recordClass = 0
  426.  *       <slot 0 value>    ----------------/    NIL
  427.  *       <slot 1 value>    --> 'Third           --> 'First
  428.  *       <slot 2 value>    --> 'Fourth          --> 'Second
  429.  *       <slot 3 value>
  430.  *
  431.  *      Then slot 0 has the name "First", slot 1 "Second", slot 2 "Third",
  432.  *      and slot 3 "Fourth".
  433.  */ struct  _FrameRecord {
  434.     uchar   recordLength[3];
  435.     uchar   recordType;         /* 0x43 */
  436.     ulong   recordFlags;        /* 0 */
  437.     vpum    recordClass;        /* Always an offset to a frame map */
  438.     vpum    frameSlotValue[1]; }; typedef struct _FrameRecord FrameRecord; #define PF_FRAME_SIZE(r) ((PF_RECORD_LENGTH(r)-sizeof(PkgRecord))/sizeof(vpum))
  439.  
  440. #define PF_FM_SORTED_BY_HASH    0x00000004 #define PF_FM_USAGE_UNKNOWN     0x00000008 #define PF_FM_HAS_PROTO_SLOT    0x00000010
  441.  
  442. struct  _FrameMap {
  443.     uchar   recordLength[3];
  444.     uchar   recordType;         /* 0x41 */
  445.     ulong   recordFlags;        /* 0 */
  446.     vpum    recordClass;        /* Combination of PF_FM_╔ above */
  447.     vpum    nextMap;            /* Offset of next map or VPUM_NIL */
  448.     vpum    frameSlotName[1];   /* Offset of slot name symbol record */ }; typedef struct _FrameMap    FrameMap; #define PF_FRAME_MAP_SIZE(r) \
  449.         ((PF_RECORD_LENGTH(r)-sizeof(PkgRecord))/sizeof(vpum)-1)
  450.  
  451. /* That's it!  The parts that I'm unsure of and would appreciate information
  452.  * about are:
  453.  *
  454.  *  -   Any of the fields called "zeroPad".
  455.  *  -   The value00000081 field in the part data header.
  456.  *  -   The meaning of the PF_FM_USAGE_UNKNOWN flag in frame maps.
  457.  *
  458.  * Plus of course any omissions and/or errors that I'm unaware of (I've not
  459.  * seen a multi-part package first hand for instance).
  460.  *
  461.  *
  462.  * Matthew Faupel
  463.  * 13 Dec 1994
  464.  */ #endif
  465.